home *** CD-ROM | disk | FTP | other *** search
- //--------------------------------------------------------------------------------------------
- // Game Controller Code
- //
- // by Philip McBride
- //
- //--------------------------------------------------------------------------------------------
-
-
- #include <FixMath.h>
- #include "GameControls.h"
- #include "extern.h"
- #include "camera.h"
- #include "document.h"
- #include "draw.h"
-
- //--------------------------------------------------------------------------------------------
- // Initialize Delta Factors
- //
- void MyInitDeltaFactors(DocumentPtr theDocument)
- {
- TQ3BoundingBox viewBBox;
- TQ3Vector3D diagonalVector;
- float maxDimension;
-
- // Get the bounding box and find the scene dimension.
- MyGetBoundingBox(theDocument, theDocument->documentGroup, &viewBBox);
- Q3Point3D_Subtract(&viewBBox.max, &viewBBox.min, &diagonalVector);
- maxDimension = Q3Vector3D_Length(&diagonalVector);
-
- // Now set the delta factors. Note, using the maxDimension
- // for the rotation factors works for some size models, but
- // you will need a more complex multipler to handle any size
- // model. Some multiplier that allows the maxDimension to
- // only have a little effect on the rotation factors. Some
- // experimentation is needed here.
- theDocument->xRotFactor = kXRotFactorBase * maxDimension;
- theDocument->yRotFactor = kYRotFactorBase * maxDimension;
- theDocument->zRotFactor = kZRotFactorBase * maxDimension;
- theDocument->xMoveFactor = kXMoveFactorBase * maxDimension;
- theDocument->yMoveFactor = kYMoveFactorBase * maxDimension;
- theDocument->zMoveFactor = kZMoveFactorBase * maxDimension;
-
- // Set up the control factor.
- theDocument->controlFactor = kControlFactorBase * maxDimension;
- }
-
- //--------------------------------------------------------------------------------------------
- // Handle Mouse Moves
- //
- void MyDoMouseMove(WindowPtr theWindow, EventRecord *theEvent)
- {
- DocumentPtr theDocument;
- Point newMouse;
- long dx, dy, oldX, oldY;
- float xRot, yRot;
- short usingControl = false;
-
- // Get the document from the window.
- theDocument = MyGetDocumentFromWindow(theWindow);
-
- // Get the current mouse position.
- GetMouse(&newMouse);
- oldX = newMouse.h;
- oldY = newMouse.v;
-
- // If the control key is down, then we're in depth mode.
- if (theEvent->modifiers & controlKey)
- usingControl = true;
-
- // Loop, moving the camera while you have the mouse down.
- while (StillDown()) {
- // Get the next mouse position.
- GetMouse(&newMouse);
-
- // Calculate the difference from the last mouse position.
- dx = newMouse.h - oldX;
- dy = oldY - newMouse.v;
-
- // If there's some difference, move the camera.
- if ((dx != 0) || (dy != 0)) {
- // Calculate the rotation about the y axis (pan) and rotate.
- yRot = ((float) dx * (kQ3Pi / 180.0)) / theDocument->width;
- MyRotateCameraY(theDocument, -yRot * theDocument->yRotFactor);
-
- // If the control key is down, move along the z axis;
- // otherwise, rotate about the x axis
- if (usingControl) {
- // Move the camera along the z axis (change in mouse's y).
- MyMoveCameraZ(theDocument, dy * theDocument->zMoveFactor);
- } else {
- // Calculate the rotation about the x axis (pitch) and rotate.
- xRot = ((float) dy * (kQ3Pi / 180.0)) / theDocument->height;
- MyRotateCameraX(theDocument, xRot * theDocument->xRotFactor);
- }
- // Update the screen for each move.
- MyUpdateScreen(theDocument);
- }
- // Set the current mouse position as the old mouse position for the next update.
- oldX = newMouse.h;
- oldY = newMouse.v;
- }
- }
-
- //--------------------------------------------------------------------------------------------
- // Check for Key
- //
- // Key checking code taken directly from "Tricks of the Mac Game Programming Gurus"
- // from chapter 5 "User Interaction." As noted in that book, since we are calling
- // this for each key we are interested in, this is not the best way to handle that
- // for effeciency. Better would be to call the getkeys once and test for all the
- // keys of interest.
- Boolean CheckKey(short keyCode)
- {
- KeyMap myKeyMap;
- short byteIndex;
- char theByte, theBit;
- char *thePointer;
-
- GetKeys(myKeyMap);
- byteIndex = keyCode >> 3;
- thePointer = (char *)&myKeyMap[0];
- theByte = *(char *)(thePointer + byteIndex);
- theBit = 1L<<(keyCode & 7);
- return ( (theByte & theBit) != 0 );
- }
-
- //--------------------------------------------------------------------------------------------
- // Handle Keyboard Moves
- //
- void MyDoKeyMove(WindowPtr theWindow, EventRecord *theEvent, char theKey)
- {
- float step = 10.0; // Arbitrary stepper for mouse/key differences
- DocumentPtr theDocument = MyGetDocumentFromWindow(theWindow);
- Boolean moveHappened;
-
- theKey = theKey;
- theEvent = theEvent;
-
- // This while loop is not very nice to any other applications
- // out there. It will stay in a loop until a mouse button is
- // hit. This is fine for games that really take over the mac,
- // but in general it would be nicer to allow many other things
- // to interrupt as well as just generally giving some idle time
- // back.
- while (!Button()) {
- moveHappened = false;
-
- // For each key of interest, check and do a move.
- if (CheckKey(iRight)) {
- MyMoveCameraX(theDocument, step * theDocument->xMoveFactor);
- moveHappened = true;
- }
- if (CheckKey(iLeft)) {
- MyMoveCameraX(theDocument, -step * theDocument->xMoveFactor);
- moveHappened = true;
- }
- if (CheckKey(iUp)) {
- MyMoveCameraY(theDocument, step * theDocument->yMoveFactor);
- moveHappened = true;
- }
- if (CheckKey(iDown)) {
- MyMoveCameraY(theDocument, -step * theDocument->yMoveFactor);
- moveHappened = true;
- }
- if ((CheckKey(iUpArrow)) || (CheckKey(iForward))) {
- MyMoveCameraZ(theDocument, step * theDocument->zMoveFactor);
- moveHappened = true;
- }
- if ((CheckKey(iDownArrow)) || (CheckKey(iBackward))) {
- MyMoveCameraZ(theDocument, -step * theDocument->zMoveFactor);
- moveHappened = true;
- }
- if (CheckKey(iPanUp)) {
- MyRotateCameraX(theDocument, (kQ3Pi/180.0) * (1.0 / step) * theDocument->xRotFactor);
- moveHappened = true;
- }
- if (CheckKey(iPanDown)) {
- MyRotateCameraX(theDocument, (-kQ3Pi/180.0) * (1.0 / step) * theDocument->xRotFactor);
- moveHappened = true;
- }
- if ((CheckKey(iRightArrow)) || (CheckKey(iPanRight))) {
- MyRotateCameraY(theDocument, (-kQ3Pi/180.0) * (1.0 / step) * theDocument->yRotFactor);
- moveHappened = true;
- }
- if ((CheckKey(iLeftArrow)) || (CheckKey(iPanLeft))) {
- MyRotateCameraY(theDocument, (kQ3Pi/180.0) * (1.0 / step) * theDocument->yRotFactor);
- moveHappened = true;
- }
- if (CheckKey(iBankL)) {
- MyRotateCameraZ(theDocument, (-kQ3Pi/180.0) * theDocument->zRotFactor);
- moveHappened = true;
- }
- if (CheckKey(iBankR)) {
- MyRotateCameraZ(theDocument, (kQ3Pi/180.0) * theDocument->zRotFactor);
- moveHappened = true;
- }
-
- // Now update the screen after a move
- if (moveHappened)
- MyUpdateScreen(theDocument);
- }
- }
-
- /*
- // This is an alternative MyDoKeyMove that makes each keyboard move during
- // the event loop. Thus being nice to the rest of the mac and any other
- // applications out there. Of course, this won't move as smooth as the
- // above version Note for this version, you would use the char codes
- // for the keys instead of the numbers (see the enum with iRight, etc.
- // in GameControls.h).
- void MyDoKeyMove(WindowPtr theWindow, EventRecord *theEvent, char theKey)
- {
- float step;
- DocumentPtr theDocument = MyGetDocumentFromWindow(theWindow);
-
- // Some arbitrary stepping values for the modifier keys (and for handling
- // the difference between keyboard and mouse)
- step = 10.0;
- if (theEvent->modifiers & shiftKey) step = 0.1;
- if (theEvent->modifiers & controlKey) step = 1.0;
- if (theEvent->modifiers & optionKey) step = 20.0;
-
- // This handles only one key at a time. To handle multiple keys
- // you need to use GetKeys to get all the keys down (that you are
- // interested in) and then instead of a switch, check for each
- // key of interest (with if statements).
- switch(theKey)
- {
- case iRight:
- MyMoveCameraX(theDocument, step * theDocument->xMoveFactor);
- MyUpdateScreen(theDocument);
- break;
- case iLeft:
- MyMoveCameraX(theDocument, -step * theDocument->xMoveFactor);
- MyUpdateScreen(theDocument);
- break;
- case iUp:
- MyMoveCameraY(theDocument, step * theDocument->yMoveFactor);
- MyUpdateScreen(theDocument);
- break;
- case iDown:
- MyMoveCameraY(theDocument, -step * theDocument->yMoveFactor);
- MyUpdateScreen(theDocument);
- break;
- case iUpArrow:
- case iForward:
- MyMoveCameraZ(theDocument, step * theDocument->zMoveFactor);
- MyUpdateScreen(theDocument);
- break;
- case iDownArrow:
- case iBackward:
- MyMoveCameraZ(theDocument, -step * theDocument->zMoveFactor);
- MyUpdateScreen(theDocument);
- break;
- case iPanUp:
- MyRotateCameraX(theDocument, (kQ3Pi/180.0) * (1.0 / step) * theDocument->xRotFactor);
- MyUpdateScreen(theDocument);
- break;
- case iPanDown:
- MyRotateCameraX(theDocument, (-kQ3Pi/180.0) * (1.0 / step) * theDocument->xRotFactor);
- MyUpdateScreen(theDocument);
- break;
- case iRightArrow:
- case iPanRight:
- MyRotateCameraY(theDocument, (-kQ3Pi/180.0) * (1.0 / step) * theDocument->yRotFactor);
- MyUpdateScreen(theDocument);
- break;
- case iLeftArrow:
- case iPanLeft:
- MyRotateCameraY(theDocument, (kQ3Pi/180.0) * (1.0 / step) * theDocument->yRotFactor);
- MyUpdateScreen(theDocument);
- break;
- case iBankL:
- MyRotateCameraZ(theDocument, (-kQ3Pi/180.0) * theDocument->zRotFactor);
- MyUpdateScreen(theDocument);
- break;
- case iBankR:
- MyRotateCameraZ(theDocument, (kQ3Pi/180.0) * theDocument->zRotFactor);
- MyUpdateScreen(theDocument);
- break;
- default:
- break;
- }
- }
- */